/******************************************************************************
 * trace.h
 * 
 * Main header file for multi-level tracing.
 * 
 * Compilation of this header file is controlled by a single macro:
 *  TRACE_LEVEL = undefined, or 0: no tracing compiled in.
 *                              1: assertions only.
 *                              2: assertions + recoverable errors.
 *                              3: above, plus warnings.
 *                              4: above, plus normal tracing.
 * 
 * Copyright (c) 1999, K A Fraser.
 */

#ifndef __KAF_TRACE_H
#define __KAF_TRACE_H

#define LEVEL_ASSERT 1
#define LEVEL_ERROR  2
#define LEVEL_WARN   3
#define LEVEL_NORMAL 4

void trc_init(void);
void trc_close(void);
void trc_trace(int level, char *file, char *func, int line, char *fmt, ...);

#undef TRC_INIT
#undef TRC_CLOSE
#undef ASSERT
#undef ERR
#undef WRN
#undef TRC

/******************************************************************************
 * If this isn't a development build, we want all tracing to compile away...
 */
#if defined(NDEBUG) || !defined(TRACE_LEVEL)
#undef TRACE_LEVEL
#define TRACE_LEVEL 0
#endif

#if TRACE_LEVEL > 0
#define ASSERT(__x)                                                     \
    if ( !(__x) )                                                       \
    {                                                                   \
        trc_trace(LEVEL_ASSERT,                                         \
                  __FILE__,                                             \
                  __FUNCTION__,                                         \
                  __LINE__,                                             \
                  " '%s' failed", #__x);                                \
    }
#define TRC_INIT()  trc_init()
#define TRC_CLOSE() trc_close()
#else
#define ASSERT(__x) ((void)0)
#define TRC_INIT()  ((void)0)
#define TRC_CLOSE() ((void)0)
#endif

#if TRACE_LEVEL > 1
#define ERR(format, args...)                                        \
    trc_trace(LEVEL_ERROR,                                          \
              __FILE__,                                             \
              __FUNCTION__,                                         \
              __LINE__,                                             \
              format , ## args)
#else
#define ERR(format, args...) ((void)0)
#endif

#if TRACE_LEVEL > 2
#define WRN(format, args...)                                        \
    trc_trace(LEVEL_WARN,                                           \
              __FILE__,                                             \
              __FUNCTION__,                                         \
              __LINE__,                                             \
              format, ## args)
#else
#define WRN(format, args...) ((void)0)
#endif

#if TRACE_LEVEL > 3
#define TRC(format, args...)                                        \
    trc_trace(LEVEL_NORMAL,                                         \
              __FILE__,                                             \
              __FUNCTION__,                                         \
              __LINE__,                                             \
              format, ## args)
#else
#define TRC(format, args...) ((void)0)
#endif

#endif /* __KAF_TRACE_H */
